/*
 * QEMU fulong 2e mini pc support
 *
 * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
 *
 * This code is licensed under the GNU GPL v2.
 */

/*
fulong 2e mini pc is based on ICT/ST loongson 2e CPU, a mips III like cpu at 800MHZ.
http://www.linux-mips.org/wiki/Fulong

loongson 2e user manual:
	http://www.loongsondeveloper.com/doc/Loongson2EUserGuide.pdf
*/

/*what is the meaning of devfn in qemu and IDSEL in bonito northbridge?

devfn   pci_slot<<3  + funno
one pci bus can have 32 devices and each device can have 8 functions.

In bonito north bridge, pci slot= IDSEL bit - 12.
For example, PCI_IDSEL_VIA686B= 17, 
pci slot = 17-12=5

so 
VIA686B_FUN0's devfn=  (5<<3)+0
VIA686B_FUN1's devfn = (5<<3) +1

qemu also uses pci address for north bridge to access south pci config register.
bus_no   [23:16]
dev_no   [15:11]
fun_no    [10:8]
reg_no    [7:2]

so function bonito_sbridge_pciaddr(bonito.c) for the translation from northbridge address 
to pci address.

*/


#include "hw.h"
#include "pc.h"
#include "fdc.h"
#include "net.h"
#include "boards.h"
#include "smbus.h"
#include "block.h"
#include "flash.h"
#include "mips.h"
#include "pci.h"
#include "qemu-char.h"
#include "sysemu.h"
#include "audio/audio.h"
#include "boards.h"

#define BIOS_FILENAME "gzrom.bin"

#define DEBUG_FULONG2E_INIT




/* PCI SLOT in fulong 2e */
#define FULONG2E_VIA_SLOT            5
#define FULONG2E_ATI_SLOT            6
#define FULONG2E_RTL8139_SLOT    7









extern PCIBus *bonito_init(qemu_irq * pic);
extern int via82c686b_init(PCIBus * bus, int devfn,qemu_irq * pic);

static void main_cpu_reset(void *opaque)
{
    CPUState *env = opaque;
    cpu_reset(env);
    /*TODO: 2E reset stuff */

}


static
    void mips_fulong2e_init(int ram_size, int vga_ram_size,
                            const char *boot_device, DisplayState * ds,
                            const char *kernel_filename, const char *kernel_cmdline,
                            const char *initrd_filename, const char *cpu_model)
{
    char buf[1024];
    unsigned long bios_offset;
    unsigned long bios_size;
    qemu_irq *i8259;
    int via_devfn;
    PCIBus *pci_bus;
   // int i;



    CPUState *env;

    /* init CPUs */
    if (cpu_model == NULL)
    {
        cpu_model = "Loongson-2E";
    }
    env = cpu_init(cpu_model);
    if (!env)
    {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }

    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
    qemu_register_reset(main_cpu_reset, env);

    /*fulong 2e has 256M ram. */
    if (ram_size != (256 * 1024 * 1024))
    {
        printf("Warnning! RAM size of fulong 2e mini pc is not 256M. Set it to 256M\n");
        ram_size = 256 * 1024 * 1024;
    }
    /* allocate RAM */
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    /*fulong 2e has a 512k flash.Winbond W39L040AP70Z */
    bios_size = 512 * 1024;
    bios_offset = ram_size + vga_ram_size;
    cpu_register_physical_memory(0x1fc00000LL, bios_size, bios_offset | IO_MEM_ROM);

    /*we do not support load kernel directly yet. Always using PMON as bios */
    /*We do not support flash operation, just loading pmon.bin as raw BIOS.
       Please use -L to set the BIOS path and -bios to set bios name. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    bios_size = load_image(buf, phys_ram_base + bios_offset);
    if ((bios_size < 0 || bios_size > BIOS_SIZE))
    {
        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n", buf);
        exit(1);
    }

    /* Init internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);
    cpu_mips_irqctrl_init();


    /* Interrupt controller */
    /* The 8259 ->IP5  */
    i8259 = i8259_init(env->irq[5]);

    /*North bridge */
    pci_bus = bonito_init(i8259);

	/*south bridge*/
    via_devfn = via82c686b_init(pci_bus, FULONG2E_VIA_SLOT << 3,i8259);
    if (via_devfn < 0)
    {
        fprintf(stderr, "via82c686b_init error \n");
        exit(1);
    }








}

QEMUMachine mips_fulong2e_machine = {
    "fulong2e",
    "Fulong 2e mini pc",
    mips_fulong2e_init,
};


